package com.pengxh.app.realityshow.media;

import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;

import com.pengxh.app.multilib.base.BaseNormalActivity;
import com.pengxh.app.multilib.widget.EasyToast;
import com.pengxh.app.realityshow.R;

import butterknife.BindView;
import butterknife.OnClick;
import cn.nodemedia.NodeCameraView;
import cn.nodemedia.NodePlayer;
import cn.nodemedia.NodePlayerDelegate;
import cn.nodemedia.NodePlayerView;
import cn.nodemedia.NodePublisher;
import cn.nodemedia.NodePublisherDelegate;

/**
 * @description: TODO
 * @author: Pengxh
 * @email: 290677893@qq.com
 * @date: 2019/11/22 23:15
 */
public class VideoPublishActivity extends BaseNormalActivity
        implements View.OnClickListener, NodePublisherDelegate, NodePlayerDelegate {

    @BindView(R.id.mNodeCameraView)
    NodeCameraView mNodeCameraView;
    @BindView(R.id.mNodePlayerView)
    NodePlayerView mNodePlayerView;

    private static final String TAG = "MainActivity";
    private boolean isStarting = false;
    private String publishURL = "rtmp://192.168.43.34:1935/live/13391634579";
    private NodePublisher nodePublisher;
    private NodePlayer nodePlayer;

    @Override
    public void initView() {
        setContentView(R.layout.activity_video);
    }

    @Override
    public void initData() {
        nodePublisher = new NodePublisher(this);
        nodePublisher.setNodePublisherDelegate(this);
        nodePublisher.setCameraPreview(mNodeCameraView, NodePublisher.CAMERA_FRONT, true);
        /**
         * 设置音频编码参数
         * 参数1 : 音频比特率
         * 参数2 : 音频编码格式,支持
         * NodePublisher.AUDIO_PROFILE_LCAAC
         * NodePublisher.AUDIO_PROFILE_HEAAC
         * NodePublisher.AUDIO_PROFILE_SPEEX
         *
         * LC意思是”Low Complexity”（低复杂性）而HE意思是”High Efficiency”（高效性）
         * */
        nodePublisher.setAudioParam(62 * 1000, NodePublisher.AUDIO_PROFILE_LCAAC);
        /**
         * 设置视频编码参数
         * 参数1 : 视频分辨率预设
         * 参数2 : 视频帧率
         * 参数3 : 视频比特率
         * 参数4 : 视频编码规格
         * NodePublisher.VIDEO_PROFILE_BASELINE
         * NodePublisher.VIDEO_PROFILE_MAIN
         * NodePublisher.VIDEO_PROFILE_HIGH
         * 参数5 : 视频输出画面是否进行镜像翻转
         * */
        nodePublisher.setVideoParam(NodePublisher.VIDEO_PPRESET_16X9_720, 30, 1812 * 1000, NodePublisher.VIDEO_PROFILE_MAIN, false);
        nodePublisher.setVideoEnable(true);
        /**
         * 降噪
         * */
        nodePublisher.setDenoiseEnable(true);
        nodePublisher.setBeautyLevel(0);//关闭美颜效果,取值范围[0,5]
        nodePublisher.setOutputUrl(publishURL);
        nodePublisher.setAutoFocus(true);
        /**
         * 设置推流类型
         * NodePublisher.PUBLISH_TYPE_LIVE
         * NodePublisher.PUBLISH_TYPE_RECORD
         * NodePublisher.PUBLISH_TYPE_APPEND
         * */
        nodePublisher.setPublishType(NodePublisher.PUBLISH_TYPE_LIVE);
        nodePublisher.setConnArgs("S:info O:1 NS:uid:10012 NB:vip:1 NN:num:209.12 O:0");
        nodePublisher.startPreview();
    }

    @Override
    public void initEvent() {
        nodePlayer = new NodePlayer(this);
        //设置播放视图的渲染器模式,可以使用SurfaceView或TextureView. 默认SurfaceView
        mNodePlayerView.setRenderType(NodePlayerView.RenderType.SURFACEVIEW);
        //设置视图的内容缩放模式
        mNodePlayerView.setUIViewContentMode(NodePlayerView.UIViewContentMode.ScaleAspectFit);
        nodePlayer.setPlayerView(mNodePlayerView);
        //设置事件回调代理
        nodePlayer.setNodePlayerDelegate(this);
        //开启硬件解码,支持4.3以上系统,初始化失败自动切为软件解码,默认开启.
        nodePlayer.setHWEnable(true);
        /**
         * 设置启动缓冲区时长,单位毫秒.此参数关系视频流连接成功开始获取数据后缓冲区存在多少毫秒后开始播放
         */
        nodePlayer.setBufferTime(300);
        /**
         * 设置最大缓冲区时长,单位毫秒.此参数关系视频最大缓冲时长.
         * RTMP基于TCP协议不丢包,网络抖动且缓冲区播完,之后仍然会接受到抖动期的过期数据包.
         * 设置改参数,sdk内部会自动清理超出部分的数据包以保证不会存在累计延迟,始终与直播时间线保持最大maxBufferTime的延迟
         */
        nodePlayer.setMaxBufferTime(1000);
        /**
         * 设置连接超时时长,单位毫秒.默认为0 一直等待.
         * 连接部分RTMP服务器,握手并连接成功后,当播放一个不存在的流地址时,会一直等待下去.
         * 如需超时,设置该值.超时后返回1006状态码.
         */
        nodePlayer.setConnectWaitTimeout(10 * 1000);
        nodePlayer.setConnArgs("S:info O:1 NS:uid:10012 NB:vip:1 NN:num:209.12 O:0");
        nodePlayer.setInputUrl(publishURL);
        /**
         * 开始播放直播视频
         */
        nodePlayer.start();
    }

    /**
     * 点击事件
     */
    @OnClick({R.id.startPush, R.id.stopPush, R.id.exchangeCamera})
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.startPush:
                if (!isStarting) {
                    int ret = nodePublisher.start();
                    Log.d(TAG, "start ret :" + ret);
                }
                break;
            case R.id.stopPush:
                if (isStarting) {
                    nodePublisher.stop();
                }
                break;
            case R.id.exchangeCamera:
                nodePublisher.switchCamera();
                nodePublisher.setFlashEnable(false);
                break;
            default:
                break;
        }
    }

    /**
     * 推流回调
     */
    @Override
    public void onEventCallback(NodePublisher nodePublisher, int event, String msg) {
        Log.d(TAG, "EventCallback:" + event + " msg:" + msg);
        handler.sendEmptyMessage(event);
        /**
         2000
         正在发布视频
         2001
         视频发布成功
         2002
         视频发布失败
         2004
         视频发布结束
         2005
         视频发布中途,网络异常,发布中断
         2100
         网络阻塞, 发布卡顿
         2101
         网络恢复, 发布流畅
         */
    }

    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 2000:
                    EasyToast.showToast("开始推流，地址是：" + publishURL, EasyToast.SUCCESS);
                    break;
                case 2001:
                    isStarting = true;
                    break;
                case 2002:
                    EasyToast.showToast("推流失败", EasyToast.ERROR);
                    break;
                case 2004:
                    EasyToast.showToast("关闭推流", EasyToast.SUCCESS);
                    isStarting = false;
                    break;
                case 2005:
                    EasyToast.showToast("网络异常,发布中断", EasyToast.ERROR);
                    break;
                case 2100:
                    // 发布端网络阻塞，已缓冲了2秒的数据在队列中
                    EasyToast.showToast("网络阻塞，发布卡顿", EasyToast.WARING);
                    break;

                //TODO 拉流handler
                case 1001:
                    EasyToast.showToast("视频连接成功", EasyToast.SUCCESS);
                    break;
                case 1002:
                    // 视频连接失败 流地址不存在，或者本地网络无法和服务端通信，回调这里。5秒后重连， 可停止
                    nodePlayer.stop();
                    break;
                case 1003:
                    // 视频开始重连,自动重连总开关
                    nodePlayer.stop();
                    break;
                case 1005:
                    // 网络异常,播放中断,播放中途网络异常，回调这里。1秒后重连，如不需要，可停止
                    nodePlayer.stop();
                    break;
                default:
                    break;
            }
        }
    };

    /**
     * 拉流回调
     */
    @Override
    public void onEventCallback(NodePlayer nodePlayer, int event, String msg) {
        Log.d("NodeMedia.NodePlayer", "onEventCallback:" + event + " msg:" + msg);
        handler.sendEmptyMessage(event);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        nodePublisher.stopPreview();
        nodePublisher.stop();
        nodePublisher.release();

        if (nodePlayer != null) {
            nodePlayer.stop();
            nodePlayer.release();
        }
    }
}